JBoss Community Archive (Read Only)

XNIO

Accessing Buffers

Data can be read from or written to buffers in two ways: using absolute operations or relative operations. The absolute operations accept a parameter which represents the absolute position of the data to be read or written, which will happen without advancing the buffer position regardless of the offset; the relative operations read or write at the current position, advancing the position by the size of the item being read or written.

When writing data to an empty buffer, either via the putXXX() operations or by reading from a channel into a buffer, the limit is generally set to be equal to the capacity, with the position advancing as the buffer is filled. For the sake of discussion, this state will be called the "filling" state.

Once the buffer is satisfactorily populated from the desired source, it may be flipped by invoking the flip() method on the buffer. This sets the limit to the position, and resets the position back to the start of the buffer, effectively allowing the data to be read out of the buffer again. This state will be referred to as the "emptying" state.

If a flipped buffer's data is not able to be fully consumed, the buffer may be restored to the filling state without losing any of its remaining data by way of the compact() method. This method effectively moves the remaining data to the beginning of the buffer, sets the position to be just after the end of this data, and resets the limit to be equal to the capacity.

A buffer may be cleared at any time by way of the clear() method. This method resets the position to zero, and sets the limit to be equal to the capacity. Thus the buffer is effectively emptied and restored to the "filling" state.

The rewind() method restarts the position back at zero. This allows a buffer in the "emptying" state which was read partially or completely to be reread in whole. A buffer in the "filling" state is effectively cleared by this method.

Often, in XNIO documentation and comments, the phrases "flipped for emptying/writing" and "compacted/emptied for filling/reading" will appear. The former refers to the "emptying" state, while the latter refers to the "filling" state.

When keeping a buffer for long periods of time and/or sharing it between tasks or threads, it is advisable to keep it in one state or the other in order to ensure consistent behavior. If your task requires the buffer to be in the opposite state for an operation, this should be done using a standard try/finally mechanism, like this:

ByteBuffer buffer = this.buffer; // starts in filling state
buffer.flip(); // switch to emptying state
try {
   perform emptying tasks;
} finally {
   buffer.compact(); // restore to filling state
}

Or:

ByteBuffer buffer = this.buffer; // starts in emptying state
buffer.compact(); // switch to filling state
try {
   perform filling tasks;
} finally {
   buffer.flip(); // restore to emptying state
}
JBoss.org Content Archive (Read Only), exported from JBoss Community Documentation Editor at 2020-03-13 13:59:27 UTC, last content change 2012-07-02 19:21:16 UTC.